#if (FEATURE_MODE == 0)
/**
 @file sys_duet2_dot1ae.c

 @author  Copyright (C) 2021 Centec Networks Inc.  All rights reserved.

 @date 2021-09-18

 @version v1.0

*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "drv_api.h"
#include "sys_usw_common.h"
#include "sys_usw_dot1ae.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_port_api.h"
#include "sys_usw_internal_port.h"
#include "sys_usw_dma.h"


/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/


/****************************************************************************
 *
* Functions
*
****************************************************************************/

int32
sys_duet2_dot1ae_set_global_cfg(uint8 lchip, void* glb_cfg)
{
    uint32 value = 0;
    uint32 cmd   = 0;
    uint32 overflow_discard = 0;
    uint32 overflow_exception = 0;
    uint32 val_ary[2] = {0};
    ctc_dot1ae_glb_cfg_t* p_glb_cfg = (ctc_dot1ae_glb_cfg_t*)glb_cfg;

    val_ary[0] = p_glb_cfg->tx_pn_thrd&0xFFFFFFFF;
    val_ary[1] = (p_glb_cfg->tx_pn_thrd>>32)&0xFFFFFFFF;
    cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AePnThreshold_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val_ary));
    val_ary[0] = p_glb_cfg->rx_pn_thrd&0xFFFFFFFF;
    val_ary[1] = (p_glb_cfg->rx_pn_thrd>>32)&0xFFFFFFFF;
    cmd = DRV_IOW(Dot1AeDecryptCtl_t, Dot1AeDecryptCtl_dot1AePnThreshold_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val_ary));

    switch (p_glb_cfg->tx_pn_overflow_action)
    {
        case CTC_EXCP_NORMAL_FWD:
            overflow_discard = 0;
            overflow_exception = 0;
            break;
        case CTC_EXCP_DISCARD:
            overflow_discard = 1;
            overflow_exception = 0;
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AePnOverflowDiscard_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &overflow_discard));
    cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AePnOverflowExceptionEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &overflow_exception));


    switch(p_glb_cfg->dot1ae_port_mirror_mode)
    {
        case CTC_DOT1AE_PORT_MIRRORED_MODE_PLAIN_TEXT:
            value = 1;
            cmd = DRV_IOW(IpeUserIdCtl_t, IpeUserIdCtl_portLogSelect_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
            value = 0;
            cmd = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_dot1AeLogMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
            break;
        case CTC_DOT1AE_PORT_MIRRORED_MODE_ENCRYPTED:
            value = 3;
            cmd = DRV_IOW(IpeUserIdCtl_t, IpeUserIdCtl_portLogSelect_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
            value = 1;
            cmd = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_dot1AeLogMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    return CTC_E_NONE;
}

int32
sys_duet2_dot1ae_get_global_cfg(uint8 lchip, void* glb_cfg)
{
    uint32 value = 0;
    uint32 value1 = 0;
    uint32 cmd   = 0;
    uint32 overflow_discard = 0;
    uint32 overflow_exception = 0;
    uint32 val_ary[2] = {0};
    ctc_dot1ae_glb_cfg_t* p_glb_cfg = (ctc_dot1ae_glb_cfg_t*)glb_cfg;

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n",__FUNCTION__);

    cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AePnThreshold_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val_ary));
    p_glb_cfg->tx_pn_thrd = ((uint64)val_ary[1]<<32) | val_ary[0];

    cmd = DRV_IOR(Dot1AeDecryptCtl_t, Dot1AeDecryptCtl_dot1AePnThreshold_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &val_ary));
    p_glb_cfg->rx_pn_thrd = ((uint64)val_ary[1]<<32) | val_ary[0];

    cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AePnOverflowDiscard_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &overflow_discard));
    cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AePnOverflowExceptionEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &overflow_exception));
    if(!overflow_discard && !overflow_exception)
    {
        p_glb_cfg->tx_pn_overflow_action = CTC_EXCP_NORMAL_FWD;
    }
    else
    {
        p_glb_cfg->tx_pn_overflow_action = CTC_EXCP_DISCARD;
    }

    cmd = DRV_IOR(IpeUserIdCtl_t, IpeUserIdCtl_portLogSelect_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    cmd = DRV_IOR(EpeHeaderEditCtl_t, EpeHeaderEditCtl_dot1AeLogMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value1));

    if((value == 1 && value1 == 0) || (DRV_FROM_TMM(lchip)))
    {
        p_glb_cfg->dot1ae_port_mirror_mode = CTC_DOT1AE_PORT_MIRRORED_MODE_PLAIN_TEXT;
    }
    else if(value == 3 && value1 == 1)
    {
        p_glb_cfg->dot1ae_port_mirror_mode = CTC_DOT1AE_PORT_MIRRORED_MODE_ENCRYPTED;
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Dot1AE Encrypt-pn-thrd: %"PRIu64", Decrypt-pn-thrd: %"PRIu64",port_mirror_pkt_type: %u\n",\
                          p_glb_cfg->tx_pn_thrd, p_glb_cfg->rx_pn_thrd, p_glb_cfg->dot1ae_port_mirror_mode);

    return CTC_E_NONE;
}


int32
sys_duet2_dot1ae_add_sc_to_asic(uint8 lchip, void* sys_chan)
{
    uint8 step = 0;
    uint32 sci_hw[2] = {0};
    uint8 index =0;
    DsDot1AePnCheck_m rx_pn;
    uint8 an = 0;
    uint32 cmd = 0;
    uint32 value = 0;
    uint16 tmp1 = 0,tmp2 = 0;
    uint16  key_index   = 0;
    sys_dot1ae_chan_t* p_sys_sec_chan = (sys_dot1ae_chan_t*)sys_chan;

    /* 1. Set an enable  */
    for (an = 0; an < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); an++)
    {
        if (CTC_IS_BIT_SET(p_sys_sec_chan->an_en, an) && p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
        {
            value = an;
            step = EpeDot1AeAnCtl0_array_1_currentAn_f - EpeDot1AeAnCtl0_array_0_currentAn_f;
            cmd = DRV_IOW(EpeDot1AeAnCtl0_t, EpeDot1AeAnCtl0_array_0_currentAn_f + step * (p_sys_sec_chan->sc_index[0] << 2));
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
        }
    }
    key_index = p_sys_sec_chan->sc_index[0]<<2;
    if(p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
    {
        /* 2. Next an */
        CTC_MAX_VALUE_CHECK(p_sys_sec_chan->next_an, MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM)-1);
        value =  p_sys_sec_chan->next_an;
        step = EpeDot1AeAnCtl1_array_1_nextAn_f - EpeDot1AeAnCtl1_array_0_nextAn_f;
        cmd = DRV_IOW(EpeDot1AeAnCtl1_t, EpeDot1AeAnCtl1_array_0_nextAn_f + step * key_index);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }
    else
    {
        sys_usw_common_get_compress_near_division_value(lchip, p_sys_sec_chan->replayProtectWindow,
                                MCHIP_CAP(SYS_CAP_DOT1AE_DIVISION_WIDE), MCHIP_CAP(SYS_CAP_DOT1AE_SHIFT_WIDE), &tmp1, &tmp2, 0);
        for(index = 0; index < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); index++)
        {
            /* 3. Replay window size */
            cmd = DRV_IOR(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));
            SetDsDot1AePnCheck(V, replayWindow_f, &rx_pn, tmp1);
            SetDsDot1AePnCheck(V, dot1AeReplayWindowShift_f, &rx_pn, tmp2);
            cmd = DRV_IOW(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));

            /* 4. Replay protect en */
            cmd = DRV_IOR(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));
            SetDsDot1AePnCheck(V, replayProtect_f, &rx_pn, p_sys_sec_chan->replayProtect? 1 : 0);
            cmd = DRV_IOW(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));
        }
    }


    /* 5. Sci */
    if (p_sys_sec_chan->sci)
    {
        SYS_USW_SET_HW_VALUE(sci_hw, p_sys_sec_chan->sci, sizeof(sci_hw));
    }
    cmd = (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX) ? DRV_IOW(DsDot1AeSci_t, DsDot1AeSci_sci_f)
    : DRV_IOW(DsEgressDot1AeSci_t, DsEgressDot1AeSci_sci_f);
    for (index = 0; index < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); index++)
    {
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index + index , cmd, &sci_hw));
    }

    return CTC_E_NONE;
}

int32
sys_duet2_dot1ae_add_sa_to_asic(uint8 lchip, void* sys_chan, uint8 sa_idx, uint32 update_flag)
{
    uint32 cmd = 0;
    uint32 value = 0;
    uint16  key_index   = 0,aes_key_index = 0;
    uint32 ebit_cbit_all[4] = {0};
    uint32 key_len = CTC_DOT1AE_KEY_LEN/2;
    int32 ret = CTC_E_NONE;
    uint32* p_key_hw = NULL;
    uint32  salt_hw[3];
    uint32 pn_mode[4] = {0};
    uint32 next_pn[2] = {0};
    uint8 icv_discard = 0;
    uint8 icv_exception = 0;
    sys_dot1ae_chan_t* p_sys_sec_chan = (sys_dot1ae_chan_t*)sys_chan;
    uint8 cipher_mode = p_sys_sec_chan->sa_cfg[sa_idx].cipher_mode;

    key_index = (p_sys_sec_chan->sc_index[0]<< 2) + (p_sys_sec_chan->sa_cfg[sa_idx].an & 0x3);
        /* tx key_index: 0-127; rx key_index: 128-255 */
    aes_key_index = key_index + ((p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)?0:128);

    /* 1. Next pn */
    if (CTC_FLAG_ISSET(update_flag, CTC_DOT1AE_SA_FLAG_NEXT_PN))
    {
        cmd = (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX) ? DRV_IOW(DsEgressDot1AePn_t, DsEgressDot1AePn_pn_f)
                                    : DRV_IOW(DsDot1AePnCheck_t, DsDot1AePnCheck_nextPn_f);
        next_pn[0] = (p_sys_sec_chan->sa_cfg[sa_idx].next_pn)&0xffffffff;
        next_pn[1] = (p_sys_sec_chan->sa_cfg[sa_idx].next_pn)>>32;
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index, cmd, &next_pn));
    }

    /* 2. Key */
    if (CTC_FLAG_ISSET(update_flag, CTC_DOT1AE_SA_FLAG_KEY))
    {
        p_key_hw = mem_malloc(MEM_DOT1AE_MODULE, key_len);
        if(NULL == p_key_hw)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_key_hw, 0 , key_len);
        SYS_USW_SET_HW_VALUE(p_key_hw,p_sys_sec_chan->sa_cfg[sa_idx].key, key_len);
        cmd = DRV_IOW(DsDot1AeAesKey_t, DsDot1AeAesKey_aesKey_f);
        ret = DRV_FIELD_IOCTL(lchip, aes_key_index, cmd, p_key_hw);
        mem_free(p_key_hw);
        if(ret < 0)
        {
            return ret;
        }

        sal_memset(salt_hw, 0, sizeof(salt_hw));

        SYS_USW_SET_HW_VALUE(salt_hw,p_sys_sec_chan->sa_cfg[sa_idx].salt, sizeof(salt_hw));
        cmd = DRV_IOW(DsDot1AeAesKey_t, DsDot1AeAesKey_salt_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, aes_key_index, cmd, salt_hw));

        cmd = DRV_IOW(DsDot1AeAesKey_t, DsDot1AeAesKey_ssci_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, aes_key_index, cmd, &p_sys_sec_chan->sa_cfg[sa_idx].ssci));

        value = p_sys_sec_chan->sa_cfg[sa_idx].cipher_suite;
        cmd = DRV_IOW(DsDot1AeAesKey_t, DsDot1AeAesKey_cipherSuite_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, aes_key_index, cmd, &value));

        if(p_sys_sec_chan->sa_cfg[sa_idx].cipher_suite > CTC_DOT1AE_CIPHER_SUITE_GCM_AES_256 && p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
        {
            cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AePnMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, pn_mode));
            CTC_BIT_SET(pn_mode[key_index/32], key_index%32);
            cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AePnMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, pn_mode));
        }
        else
        {
            cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AePnMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, pn_mode));
            CTC_BIT_UNSET(pn_mode[key_index/32], key_index%32);
            cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AePnMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, pn_mode));
        }
    }

    /* 3. cipher mode */
    if (CTC_FLAG_ISSET(update_flag, CTC_DOT1AE_SA_FLAG_ENCRYPTION))
    {
        cmd = DRV_IOW(DsDot1AeAesKey_t, DsDot1AeAesKey_cipherMode_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, aes_key_index, cmd, &cipher_mode));
        cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AeTciEbitCbit_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &ebit_cbit_all));
        if(p_sys_sec_chan->sa_cfg[sa_idx].ebit_cbit)
        {
            CTC_BIT_SET(ebit_cbit_all[key_index/32], key_index%32);
        }
        else
        {
            CTC_BIT_UNSET(ebit_cbit_all[key_index/32], key_index%32);
        }
        cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AeTciEbitCbit_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &ebit_cbit_all));
    }

    /* 4. Icv check error action and validateFrames */
    if (CTC_FLAG_ISSET(update_flag, CTC_DOT1AE_SA_FLAG_ICV_ERROR_ACTION)
        && p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX)
    {
         icv_discard = p_sys_sec_chan->sa_cfg[sa_idx].icv_discard;
        cmd = DRV_IOW(DsDot1AePnCheck_t, DsDot1AePnCheck_icvCheckFailDiscard_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index, cmd, &icv_discard));

        icv_exception = p_sys_sec_chan->sa_cfg[sa_idx].icv_exception;
        cmd = DRV_IOW(DsDot1AePnCheck_t, DsDot1AePnCheck_icvCheckFailException_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index, cmd, &icv_exception));
        
    }

    return CTC_E_NONE;
}

int32
sys_duet2_dot1ae_build_sc_index(uint8 lchip, void* sys_chan)
{
    sys_usw_opf_t opf;
    uint32  offset = 0;
    sys_dot1ae_chan_t* p_sys_sec_chan = (sys_dot1ae_chan_t*)sys_chan;

    /* Build sc index used opf */
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type = usw_dot1ae_master[lchip]->dot1ae_opf_type;
    opf.pool_index = (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX) ? 0 : 1;
    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, 1, &offset));
    p_sys_sec_chan->sc_index[0] = offset &0x1F;
    p_sys_sec_chan->dp_bmp =1;
    SYS_DOT1AE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "add sec_chan,chan_id:%d (sc_idx:%d) dir:%d\n", p_sys_sec_chan->chan_id, p_sys_sec_chan->sc_index[0], p_sys_sec_chan->dir);

    return CTC_E_NONE;
}

int32
sys_duet2_dot1ae_free_sc_index(uint8 lchip, void* sys_chan)
{
    sys_usw_opf_t opf;
    sys_dot1ae_chan_t* p_sys_sec_chan = (sys_dot1ae_chan_t*)sys_chan;

    opf.pool_type = usw_dot1ae_master[lchip]->dot1ae_opf_type;
    opf.pool_index = (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX) ? 0 : 1;

    return sys_usw_opf_free_offset(lchip, &opf, 1, p_sys_sec_chan->sc_index[0]);
}

int32
sys_duet2_dot1ae_reset_sec_chan_cfg(uint8 lchip, void* sys_chan)
{
    uint32 cmd = 0;
    uint32 value[2] = {0};
    uint16  key_index   = 0,aes_key_index = 0;
    uint8 loop = 0;
    uint8 step = 0;
    uint32 ebit_cbit_all[4] = {0};
    uint32 sci_hw[2] = {0};
    sys_dot1ae_chan_t* p_sc_info = (sys_dot1ae_chan_t*) sys_chan;
    DsDot1AePnCheck_m rx_pn_cfg;
    DsEgressDot1AePn_m tx_pn_cfg;
    DsDot1AeAesKey_m aes_key;
    DsDot1AeDecryptConfig_m Decrypt_cfg;
    sal_memset(&aes_key, 0, sizeof(aes_key));
    sal_memset(&rx_pn_cfg, 0, sizeof(rx_pn_cfg));
    sal_memset(&tx_pn_cfg, 0, sizeof(tx_pn_cfg));
    sal_memset(&Decrypt_cfg, 0, sizeof(Decrypt_cfg));


    for (loop = 0; loop < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); loop++)
    {
        key_index = (p_sc_info->sc_index[0] << 2) + (loop & 0x3);

        aes_key_index = key_index + ((p_sc_info->dir == CTC_DOT1AE_SC_DIR_TX)? 0 : 128);

        /*reset aes key*/
        cmd = DRV_IOW(DsDot1AeAesKey_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, aes_key_index, cmd, &aes_key);



        /*next pn/windown size*/
        if (p_sc_info->dir == CTC_DOT1AE_SC_DIR_TX)
        {
            cmd = DRV_IOW(DsEgressDot1AePn_t, DRV_ENTRY_FLAG);
            value[0] = 1;
            SetDsEgressDot1AePn(A, pn_f, &tx_pn_cfg, &value);
            DRV_IOCTL(lchip, key_index, cmd, &tx_pn_cfg);

            /*an/next an */
            value[0] = 0;
            step = EpeDot1AeAnCtl1_array_1_nextAn_f - EpeDot1AeAnCtl1_array_0_nextAn_f;
            cmd = DRV_IOW(EpeDot1AeAnCtl1_t, EpeDot1AeAnCtl1_array_0_nextAn_f + step * key_index);
            DRV_FIELD_IOCTL(lchip, 0, cmd, &value);

            step = EpeDot1AeAnCtl0_array_1_currentAn_f - EpeDot1AeAnCtl0_array_0_currentAn_f;
            cmd = DRV_IOW(EpeDot1AeAnCtl0_t, EpeDot1AeAnCtl0_array_0_currentAn_f + step * key_index);
            DRV_FIELD_IOCTL(lchip, 0, cmd, &value);

            /* e&c bit*/
            cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AeTciEbitCbit_f);
            DRV_FIELD_IOCTL(lchip, 0, cmd, &ebit_cbit_all);
            CTC_BIT_UNSET(ebit_cbit_all[key_index / 32], key_index % 32);
            cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AeTciEbitCbit_f);
            DRV_FIELD_IOCTL(lchip, 0, cmd, &ebit_cbit_all);

            /*aepnMode*/
            cmd = DRV_IOR(EpePktProcCtl_t, EpePktProcCtl_dot1AePnMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, ebit_cbit_all));
            CTC_BIT_UNSET(ebit_cbit_all[key_index / 32], (key_index % 32));
            cmd = DRV_IOW(EpePktProcCtl_t, EpePktProcCtl_dot1AePnMode_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, ebit_cbit_all));

            cmd = DRV_IOW(DsEgressDot1AeSci_t, DsEgressDot1AeSci_sci_f);
            DRV_FIELD_IOCTL(lchip, key_index, cmd, &sci_hw);
        }
        else
        {
            cmd = DRV_IOW(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
            value[0] = 1;
            SetDsDot1AePnCheck(A, nextPn_f, &rx_pn_cfg, &value);
            DRV_IOCTL(lchip, key_index, cmd, &rx_pn_cfg);

            cmd = DRV_IOW(DsDot1AeSci_t, DsDot1AeSci_sci_f);
            DRV_FIELD_IOCTL(lchip, key_index, cmd, &sci_hw);

            cmd = DRV_IOW(DsDot1AeDecryptConfig_t, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, key_index, cmd, &Decrypt_cfg);
        }

    }

    return CTC_E_NONE;
}


int32
sys_duet2_dot1ae_register_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 value = 0;
    uint16 lport = 0;
    EpePktProcCtl_m    epe_pkt_ctl;
    Dot1AeDecryptCtl_m decrypt_ctl;
    IpeIntfMapperCtl_m intf_ctl;

    value = 7;
    cmd = DRV_IOW(NetRxMiscChanPktLenChkCtl_t, NetRxMiscChanPktLenChkCtl_cfgMiscMinLenSelId_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 9, cmd, &value));
    cmd = DRV_IOW(NetRxMiscChanPktLenChkCtl_t, NetRxMiscChanPktLenChkCtl_cfgMiscMinLenSelId_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 10, cmd, &value));

    cmd = DRV_IOW(NetRxMiscChanPktLenChkCtl_t, NetRxMiscChanPktLenChkCtl_cfgMiscMaxLenSelId_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 9, cmd, &value));
    cmd = DRV_IOW(NetRxMiscChanPktLenChkCtl_t, NetRxMiscChanPktLenChkCtl_cfgMiscMaxLenSelId_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 10, cmd, &value));

    /* IpeUserIdCtl */
    value = 1;
    cmd = DRV_IOW(IpeUserIdCtl_t, IpeUserIdCtl_unknownDot1AeSciDiscard_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    /*IpeFwdCtl*/
    value = 1;
    cmd = DRV_IOW(IpeFwdCtl_t, IpeFwdCtl_hardErrorDebugEn_f);/*TMM..*/
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    value = 1;
    cmd = DRV_IOW(IpeUserIdCtl_t, IpeUserIdCtl_unknownDot1AePacketDiscard_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    value = 1;
    cmd = DRV_IOW(IpeUserIdCtl_t, IpeUserIdCtl_portLogSelect_f);   /*rx, only mirror plain pkt*/
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    /* EpeHeaderEditCtl */
    value = 0;
    cmd = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_dot1AeLogMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    /*MacSecDecryptCtl*/
    value = 1;
    cmd = DRV_IOW(MacSecDecryptCtl_t, MacSecDecryptCtl_cipherModeMismatchDiscard_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    value = 1;
    cmd = DRV_IOW(MacSecDecryptCtl_t, MacSecDecryptCtl_hostSciLowBits_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    /* IpeIntfMapperCtl */
    cmd = DRV_IOR(IpeIntfMapperCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &intf_ctl));

    SetIpeIntfMapperCtl(V, dot1AeDisableLearning_f, &intf_ctl, 1);
    SetIpeIntfMapperCtl(V, bypassPortCrossConnectDisable_f, &intf_ctl, 1);

    cmd = DRV_IOW(IpeIntfMapperCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &intf_ctl));

    /* EpePktProcCtl */
    cmd = DRV_IOR(EpePktProcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt_ctl));
    SetEpePktProcCtl(V, dot1AePnThreshold_f, &epe_pkt_ctl, 0xc0000000);
    SetEpePktProcCtl(V, dot1AePnMatchSwitchEn_f,    &epe_pkt_ctl, 1);
    SetEpePktProcCtl(V, dot1AePnMatchExceptionEn_f, &epe_pkt_ctl, 0);
    SetEpePktProcCtl(V, dot1AePnOverflowDiscard_f, &epe_pkt_ctl, 1);
    SetEpePktProcCtl(V, dot1AePnOverflowExceptionEn_f, &epe_pkt_ctl, 0);
    SetEpePktProcCtl(V, dot1AeXpnEn_f, &epe_pkt_ctl, 1);

    cmd = DRV_IOW(EpePktProcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt_ctl));

    /* Dot1AeDecryptCtl */
    cmd = DRV_IOR(Dot1AeDecryptCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &decrypt_ctl));
    SetDot1AeDecryptCtl(V, dot1AePnThreshold_f, &decrypt_ctl, 0xc0000000);
    cmd = DRV_IOW(Dot1AeDecryptCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &decrypt_ctl));

    /* IpeE2iLoopCtl */
    value = 0;
    cmd = DRV_IOW(IpeE2iLoopCtl_t, IpeE2iLoopCtl_dot1AeDecryptPortControlEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    value = 1;
    cmd = DRV_IOW(IpeE2iLoopCtl_t, IpeE2iLoopCtl_dot1AeEncryptPortControlEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    cmd = DRV_IOW(IpeE2iLoopCtl_t, IpeE2iLoopCtl_dot1AeEncryptedLoopbackPort_f);
    CTC_ERROR_RETURN(sys_usw_internal_port_get_rsv_port(lchip, SYS_INTERNAL_PORT_TYPE_WLAN_ENCAP, 0, &lport));
    value = lport;
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    /* QWriteDot1AeCtl */
    value = MCHIP_CAP(SYS_CAP_CHANID_MAC_ENCRYPT);
    cmd = DRV_IOW(QWriteDot1AeCtl_t, QWriteDot1AeCtl_dot1AeEncryptChannel_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    value = MCHIP_CAP(SYS_CAP_CHANID_MAC_DECRYPT);
    cmd = DRV_IOW(QWriteDot1AeCtl_t, QWriteDot1AeCtl_dot1AeDecryptChannel_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    return CTC_E_NONE;
}

STATIC int32
_sys_duet2_dot1ae_update_sec_chan_an_en(uint8 lchip,sys_dot1ae_chan_t* p_sys_sec_chan, uint32 an_bitmap)
{
    uint8 an = 0;
    uint32 enable = 0;
    uint32 enable_old = 0;
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 value = 0;
    uint8 step = 0;
    uint16  key_index   = 0,aes_key_index = 0;
    uint8 key[CTC_DOT1AE_KEY_LEN/2] = {0};

    /*if current sec-chan is binded, add to asic, or update db only*/
    for (an = 0; an < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); an++)
    {
        if (!CTC_IS_BIT_SET(an_bitmap, an)
            && (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX))
        {
            /*rx need clear key when an disable*/
            continue;
        }
        enable = CTC_IS_BIT_SET(an_bitmap, an);

        if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
        {
            if (CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
            {
                value = an;
                step = EpeDot1AeAnCtl0_array_1_currentAn_f - EpeDot1AeAnCtl0_array_0_currentAn_f;
                cmd = DRV_IOW(EpeDot1AeAnCtl0_t, EpeDot1AeAnCtl0_array_0_currentAn_f + step * (p_sys_sec_chan->sc_index[0] << 2));
                ret = DRV_FIELD_IOCTL(lchip, 0, cmd, &value);
            }
            p_sys_sec_chan->an_en = an_bitmap;
        }
        else
        {
            enable_old = CTC_IS_BIT_SET(p_sys_sec_chan->an_en, an);
            if (enable)
            {
                CTC_BIT_SET(p_sys_sec_chan->an_en, an);
            }
            if (enable != enable_old)
            {/*clear key when an disable*/
                key_index = (p_sys_sec_chan->sc_index[0]<< 2) + an;
                /* tx key_index: 0-127; rx key_index: 128-255 */
                aes_key_index = key_index + ((p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)?0:128);
                cmd = DRV_IOW(DsDot1AeAesKey_t, DsDot1AeAesKey_aesKey_f);
                ret = DRV_FIELD_IOCTL(lchip, aes_key_index, cmd, (uint32*)key);
            }

            if (!enable || ret != CTC_E_NONE)
            {
                CTC_BIT_UNSET(p_sys_sec_chan->an_en, an);
            }
        }
    }

    return ret;
}

int32
sys_duet2_dot1ae_update_sec_chan(uint8 lchip, void* sys_chan, void* sc)
{
    uint32 cmd =0;
    uint32 value = 0;
    uint16 tmp1 = 0, tmp2 = 0;
    uint32 key_index = 0;
    uint8 step = 0;
    uint32 sci_hw[2] = {0};
    uint8 index =0;
    DsDot1AePnCheck_m rx_pn;
    sys_dot1ae_chan_t* p_sys_sec_chan = (sys_dot1ae_chan_t*)sys_chan;
    ctc_dot1ae_sc_t* p_sc = (ctc_dot1ae_sc_t*)sc;

    if (CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
    {
        key_index = p_sys_sec_chan->sc_index[0]  <<2;
    }

    /* update sec-chan property in db, if currrent sec-chan is binded, update asic */
    switch (p_sc->property)
    {
    case CTC_DOT1AE_SC_PROP_AN_EN:
        CTC_ERROR_RETURN(_sys_duet2_dot1ae_update_sec_chan_an_en(lchip,p_sys_sec_chan, p_sc->data));
        break;
    case CTC_DOT1AE_SC_PROP_NEXT_AN:
        p_sys_sec_chan->next_an = p_sc->data;
        if(!CTC_IS_BIT_SET(p_sys_sec_chan->an_valid,p_sys_sec_chan->next_an))
        {
            return CTC_E_NOT_READY;
        }
        if (CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
        {
            value =  p_sc->data;
            step = EpeDot1AeAnCtl1_array_1_nextAn_f - EpeDot1AeAnCtl1_array_0_nextAn_f;
            cmd = DRV_IOW(EpeDot1AeAnCtl1_t, EpeDot1AeAnCtl1_array_0_nextAn_f + step * key_index);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
        }
        break;
    case CTC_DOT1AE_SC_PROP_INCLUDE_SCI :
        p_sys_sec_chan->include_sci=  p_sc->data ? 1: 0;
        if (CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
        {
            sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
            ctc_slistnode_t        *node = NULL;
            if (1 == p_sys_sec_chan->binding_type)
            {
                sys_com_dot1ae_bind_sc_t bind_sc;
                CTC_SLIST_LOOP(p_sys_sec_chan->bind_mem_list, node)
                {
                    p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
                    sal_memset(&bind_sc, 0, sizeof(bind_sc));
                    bind_sc.include_sci = p_sc->data;
                    bind_sc.gport = p_sec_chan_bind_node->value;
                    CTC_ERROR_RETURN(sys_usw_nh_update_dot1ae(lchip, (void*)(&bind_sc)));
                }
            }
            else if (0 == p_sys_sec_chan->binding_type)
            {
                CTC_SLIST_LOOP(p_sys_sec_chan->bind_mem_list, node)
                {
                    p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
                    p_sys_sec_chan->gport = p_sec_chan_bind_node->value;
                }
                    value =  p_sc->data;
            }
        }
        break;
    case CTC_DOT1AE_SC_PROP_SCI :
        if (p_sys_sec_chan->sci)
        {
            sal_memcpy(p_sys_sec_chan->sci, (uint8*)p_sc->ext_data, SYS_DOT1AE_SCI_LEN);
        }
        if (CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
        {
            SYS_USW_SET_HW_VALUE(sci_hw, (uint8*)p_sc->ext_data, sizeof(sci_hw));
            cmd = (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX) ? DRV_IOW(DsDot1AeSci_t, DsDot1AeSci_sci_f)
            : DRV_IOW(DsEgressDot1AeSci_t, DsEgressDot1AeSci_sci_f);
            for (index = 0; index < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); index++)
            {
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index + index , cmd, &sci_hw));
            }
        }
        break;
    case CTC_DOT1AE_SC_PROP_REPLAY_WINDOW_SIZE :
        p_sys_sec_chan->replayProtectWindow = p_sc->data;
        if (CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
        {
            sys_usw_common_get_compress_near_division_value(lchip, p_sc->data,
                                                            MCHIP_CAP(SYS_CAP_DOT1AE_DIVISION_WIDE), MCHIP_CAP(SYS_CAP_DOT1AE_SHIFT_WIDE), &tmp1, &tmp2, 0);
            for (index = 0; index < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); index++)
            {
                cmd = DRV_IOR(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));
                SetDsDot1AePnCheck(V, replayWindow_f, &rx_pn, tmp1);
                SetDsDot1AePnCheck(V, dot1AeReplayWindowShift_f, &rx_pn, tmp2);
                cmd = DRV_IOW(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));
            }
        }
        break;
    case CTC_DOT1AE_SC_PROP_REPLAY_PROTECT_EN:
        p_sys_sec_chan->replayProtect = p_sc->data;
        if (CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
        {
            for (index = 0; index < MCHIP_CAP(SYS_CAP_DOT1AE_AN_NUM); index++)
            {
                cmd = DRV_IOR(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));
                SetDsDot1AePnCheck(V, replayProtect_f, &rx_pn, p_sc->data? 1 : 0);
                cmd = DRV_IOW(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index + index, cmd, &rx_pn));
            }
        }
        break;
    default :
        break;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_duet2_dot1ae_unbind_traverse(sys_dot1ae_chan_t* p_sys_chan,void* user_data)
{
    uint32 gport = 0;
    uint8 lchip=0;
    sys_usw_opf_t opf;
    ctc_slistnode_t        *node = NULL;
    uint8 found = 0;
    sys_dot1ae_chan_bind_node_t* p_sec_chan_bind_node = NULL;
    sys_com_dot1ae_bind_sc_t* p_bind_sc = NULL;

    sys_traverse_t* traversal_data = (sys_traverse_t *)user_data;
    p_bind_sc = (sys_com_dot1ae_bind_sc_t*)traversal_data->data;
    gport = p_bind_sc->gport;
    lchip = traversal_data->value1;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    if (p_sys_chan->valid&& CTC_SLISTCOUNT(p_sys_chan->bind_mem_list)
        &&(p_sys_chan->binding_type == p_bind_sc->type)&&
        (p_sys_chan->dir == p_bind_sc->dir))
    {
        CTC_SLIST_LOOP(p_sys_chan->bind_mem_list, node)
        {
            p_sec_chan_bind_node = _ctc_container_of(node, sys_dot1ae_chan_bind_node_t, head);
            if (gport == p_sec_chan_bind_node->value)
            {
                found = 1;
                break;
            }
        }
        if (1 == found)
        {
            ctc_slist_delete_node(p_sys_chan->bind_mem_list, &(p_sec_chan_bind_node->head));
            mem_free(p_sec_chan_bind_node);
            if (!CTC_SLISTCOUNT(p_sys_chan->bind_mem_list))
            {
                opf.pool_type = usw_dot1ae_master[lchip]->dot1ae_opf_type;
                opf.pool_index = ((p_sys_chan->dir == CTC_DOT1AE_SC_DIR_TX) ? 0 : 1);
                sys_usw_opf_free_offset(lchip, &opf, 1, p_sys_chan->sc_index[0]);
                SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DOT1AE, SYS_WB_APPID_DOT1AE_SUBID_MASTER, 1);
                p_sys_chan->enable = 0;
                p_sys_chan->sc_index[0] = 0;
                p_sys_chan->binded=0;
            }
        }
    }
    return CTC_E_NONE;
}

int32
sys_duet2_dot1ae_unbind_sec_chan(uint8 lchip, void* bind_sc)
{
    sys_traverse_t user_data;
    sal_memset(&user_data, 0 , sizeof(sys_traverse_t));
    user_data.data =  (void*)bind_sc;
    user_data.value1 = lchip;
    CTC_ERROR_RETURN(ctc_hash_traverse(usw_dot1ae_master[lchip]->chan_hash, (hash_traversal_fn)_sys_duet2_dot1ae_unbind_traverse, (void *)&user_data));
    return CTC_E_NONE;
}

int32
sys_duet2_dot1ae_chan_wb_restore(uint8 lchip, void* p_sys_chan)
{
    ds_t ds;
    uint8* p_key_hw = NULL;
    uint32 val_ary[2] = {0};
    uint32  salt_hw[3]={0};
    uint32 cmd = 0;
    uint32 value=0;
    uint16 key_index = 0;
    uint32 aes_key_index = 0;
    uint8 step = 0;
    uint8 sa_idx = 0;
    sys_usw_opf_t opf;
 

    sys_dot1ae_chan_t* p_sys_sec_chan = (sys_dot1ae_chan_t*)p_sys_chan;
    key_index = p_sys_sec_chan->sc_index[0]<< 2;

    if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)
    {
        step = EpeDot1AeAnCtl1_array_1_nextAn_f - EpeDot1AeAnCtl1_array_0_nextAn_f;
        cmd = DRV_IOR(EpeDot1AeAnCtl1_t, EpeDot1AeAnCtl1_array_0_nextAn_f + step * key_index);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
        p_sys_sec_chan->next_an = value;
    }
    else
    {
        cmd = DRV_IOR(DsDot1AePnCheck_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, key_index, cmd, ds));
        p_sys_sec_chan->replayProtect = GetDsDot1AePnCheck(V, replayProtect_f, &ds);
        p_sys_sec_chan->replayProtectWindow = GetDsDot1AePnCheck(V, replayWindow_f, &ds);
    }

    for (sa_idx = 0; sa_idx < 2; sa_idx++)
    {
        key_index = (p_sys_sec_chan->sc_index[0] << 2) + (p_sys_sec_chan->sa_cfg[sa_idx].an & 0x3);
        /* tx key_index: 0-127; rx key_index: 128-255 */
        aes_key_index = key_index + ((p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX)? 0 : (MCHIP_CAP(SYS_CAP_DOT1AE_RX_CHAN_NUM) << 2));

        /* pn */
        cmd = (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX) ? DRV_IOR(DsEgressDot1AePn_t, DsEgressDot1AePn_pn_f)
                                    : DRV_IOR(DsDot1AePnCheck_t, DsDot1AePnCheck_nextPn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, key_index, cmd, val_ary));
        p_sys_sec_chan->sa_cfg[sa_idx].next_pn = ((uint64)val_ary[1] << 32) | val_ary[0];

        if (p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_RX)
        {
            if (p_sys_sec_chan->replayProtect)
            {
                if (p_sys_sec_chan->sa_cfg[sa_idx].next_pn > p_sys_sec_chan->replayProtectWindow)
                {
                    p_sys_sec_chan->sa_cfg[sa_idx].lowest_pn = p_sys_sec_chan->sa_cfg[sa_idx].next_pn - p_sys_sec_chan->replayProtectWindow;
                }
            }
            else
            {
                p_sys_sec_chan->sa_cfg[sa_idx].lowest_pn = p_sys_sec_chan->sa_cfg[sa_idx].next_pn;
            }
        }

        /* key */
        cmd = DRV_IOR(DsDot1AeAesKey_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, aes_key_index, cmd, &ds));
        p_sys_sec_chan->sa_cfg[sa_idx].cipher_mode = GetDsDot1AeAesKey(V, cipherMode_f, &ds);
        p_sys_sec_chan->sa_cfg[sa_idx].cipher_suite = GetDsDot1AeAesKey(V, cipherSuite_f, &ds);
        p_sys_sec_chan->sa_cfg[sa_idx].ssci = GetDsDot1AeAesKey(V, ssci_f, &ds);
        GetDsDot1AeAesKey(A, salt_f, &ds, salt_hw);
        SYS_USW_SET_USER_VALUE(p_sys_sec_chan->sa_cfg[sa_idx].salt, salt_hw, sizeof(salt_hw));

        p_key_hw = mem_malloc(MEM_DOT1AE_MODULE, CTC_DOT1AE_KEY_LEN);
        if (NULL == p_key_hw)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_key_hw, 0 , CTC_DOT1AE_KEY_LEN);
        GetDsDot1AeAesKey(A, aesKey_f, &ds, p_key_hw);
        if ((CTC_DOT1AE_CIPHER_SUITE_GCM_AES_128 == p_sys_sec_chan->sa_cfg[sa_idx].cipher_suite) || (CTC_DOT1AE_CIPHER_SUITE_GCM_AES_XPN_128 == p_sys_sec_chan->sa_cfg[sa_idx].cipher_suite))
        {
            SYS_USW_SET_USER_VALUE(p_sys_sec_chan->sa_cfg[sa_idx].key, (uint32*)p_key_hw, CTC_DOT1AE_KEY_LEN / 2);
        }
        else
        {
            SYS_USW_SET_USER_VALUE(p_sys_sec_chan->sa_cfg[sa_idx].key, (uint32*)p_key_hw, CTC_DOT1AE_KEY_LEN);
        }
        mem_free(p_key_hw);

        if (0 != p_sys_sec_chan->binding_type)
        {
            p_sys_sec_chan->sa_cfg[sa_idx].no_encryption = (p_sys_sec_chan->sa_cfg[sa_idx].cipher_mode == 5 )? 1 : 0;
        }
        else
        {
            p_sys_sec_chan->sa_cfg[sa_idx].no_encryption = (p_sys_sec_chan->sa_cfg[sa_idx].cipher_mode == 3 )? 1 : 0;
        }
    }
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    /*recover opf*/
    if (p_sys_sec_chan->binded || CTC_SLISTCOUNT(p_sys_sec_chan->bind_mem_list))
    {
        opf.pool_type = usw_dot1ae_master[lchip]->dot1ae_opf_type;
        opf.pool_index = ((p_sys_sec_chan->dir == CTC_DOT1AE_SC_DIR_TX) ? 0 : 1) ;
        CTC_ERROR_RETURN(sys_usw_opf_alloc_offset_from_position(lchip, &opf, 1, p_sys_sec_chan->sc_index[0]));
    }
    return CTC_E_NONE;
}

#endif